﻿using System;
using System.Diagnostics;
using System.Threading;
using Rsdn.SmartApp;

namespace Rsdn.Janus
{
    using System.Windows.Forms;

    internal partial class InvisibleInitializationForm : Form
    {
        private bool abortApplication = false;
        private ServiceManager rootManager;
        private JanusHost host;

        public InvisibleInitializationForm(ServiceManager rootManager, JanusHost host)
        {
            Visible = false;
            InitializeComponent();
            this.rootManager = rootManager;
            this.host = host;
        }

        public bool AbortApplication
        {
            get { return abortApplication; }
            set { abortApplication = value; }
        }

        private void InvisibleInitializationForm_Load(object sender, System.EventArgs e)
        {
            infoLabel.Text = ApplicationInfo.NameWithVersion;
            Visible = false;
            InitApplication();
            Close();
        }

        private void InitApplication()
        {
            // use the form (with application context) because
            // we need active message loop
            try
            {
                //Проверка наличия пользователя
                if (!LocalUser.UserExists())
                {
                    using (var ouf = new OptionsUserForm(host, true))
                    {
                        DialogResult result = ouf.ShowDialog();
                        if (result != DialogResult.OK)
                        {
                            abortApplication = true;
                            return;
                        }
                    }
                }

                rootManager.SetSplashMessage(SR.Splash.CheckDatabase);

                if (!DBSchemaManager.CheckDB(host))
                {
                    // User cancelled.
                    TraceVerbose("User cancelled");
                    abortApplication = true;
                    return;
                }

                if (DBSchemaManager.IsNeedRestructuring(host))
                {
                    ManualResetEvent operationCompleted = new ManualResetEvent(false);

                    ProgressWorker.Run(
                        rootManager,
                        false,
                        progressVisualizer =>
                        {
                            progressVisualizer.SetProgressText(SR.Splash.RestructureDatabase);
                            try
                            {
                                DBSchemaManager.Restruct(host);
                                DatabaseManager.ClearTopicInfo(host);
                                Config.Instance.BadRestruct = false;
                            }
                            catch (Exception ex)
                            {
                                Config.Instance.BadRestruct = true;
                                Config.Save();
                                using (ExceptionForm exceptionForm = new ExceptionForm(null, ex, false))
                                {
                                    exceptionForm.ShowDialog();
                                }
                            }
                            finally
                            {
                                // сигнализируем об окончании работы второго потока
                                operationCompleted.Set();
                            }
                        }
                        );

                    // блокируем поток, пока не завершится реструктуризация БД
                    operationCompleted.WaitOne();
                }

                // Проверяем наличие таблички topic_info
                DatabaseManager.CheckTopicInfoIntegrity(host);

                TraceVerbose("DB ready");
            }
            catch (LocalUserNotFoundException)
            {
                MessageBox.Show(
                    SR.JanusImpossibleWork,
                    ApplicationInfo.ApplicationName,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                throw;
            }
        }

        #region Debug

        private static readonly Stopwatch _sw = Stopwatch.StartNew();

        [Conditional("DEBUG")]
        private static void TraceVerbose(string label)
        {
            Debug.WriteLineIf(TraceSwitch.TraceVerbose, _sw.Elapsed + ": " + label, TraceSwitch.DisplayName);
        }

        private static TraceSwitch _traceSwitch;

        private static TraceSwitch TraceSwitch
        {
            get { return _traceSwitch ?? (_traceSwitch = new TraceSwitch("EntryPoint", "Program entry point trace switch")); }
        }

        #endregion

    }
}
